#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>

static char* filename = "/home/ngx/code/test/test.txt";

void file_read(const char* filename)
{
    struct file*  filp;
    struct inode* inode;
    mm_segment_t  fs;
    off_t         fsize;
    char*         buf   = NULL;
    unsigned long magic = 0;

    printk("<1>start....\n");
    filp = filp_open(filename, O_RDONLY, 0666);
    if (IS_ERR(filp)) {
        printk("open error...\n");
        return;
    }

    inode = filp->f_inode;
    magic = inode->i_sb->s_magic;
    printk("<1>file system magic:%li \n", magic);
    printk("<1>super blocksize:%li \n", inode->i_sb->s_blocksize);
    printk("<1>inode %li \n", inode->i_ino);
    fsize = inode->i_size;
    printk("<1>file size:%i \n", (int)fsize);

    buf = (char*)kcalloc(fsize + 1, 1, GFP_KERNEL);
    if (!buf) {
        printk("malloc failed.\n");
        return;
    }

    fs = get_fs();
    set_fs(KERNEL_DS);
    printk("<1>read to buf ...\n");
    vfs_read(filp, buf, fsize, &(filp->f_pos));
    set_fs(fs);

    buf[fsize] = '\0';
    printk("<1>The File Content is:\n");
    printk("%s\n", buf);

    kfree(buf);
    filp_close(filp, NULL);
}

void file_write(char* filename, char* data)
{
    struct file* filp;
    mm_segment_t fs;
    filp = filp_open(filename, O_RDWR | O_APPEND, 0666);
    if (IS_ERR(filp)) {
        printk("open error...\n");
        return;
    }
    fs = get_fs();
    set_fs(KERNEL_DS);
    vfs_write(filp, data, strlen(data), &filp->f_pos);
    set_fs(fs);
    filp_close(filp, NULL);
}

static int hello_init(void)
{
    printk("<1>Read File from Kernel.\n");
    file_read(filename);
    file_write(filename, "kernel write test\n");
    return 0;
}

static void hello_cleanup(void) { printk("byebye module.\n"); }

module_init(hello_init);
module_exit(hello_cleanup);
MODULE_LICENSE("GPL");
